import axios from 'axios'
import store from '@/store/index.js'
import router from '@/router'
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  /*
    axios请求的完整地址是:baseURL + url
    不能让axios直接去请求http://开头的外链地址,而是请求/开头还得命中本地开发服务器里代理规则

    请求的路径问题:
    如果是./开头地址,找当前文件夹
    如果是http开头地址,找外部链接服务器(链接网络)
    如果是/开头,忽略文件夹,直接找当前运行时,所在的服务器
  */
  timeout: 5000
})
// 请求拦截器
service.interceptors.request.use(
  config => {
    // js文件中不能直接使用this.$store
    // this不是Vue组件对象,无法找到原型链上$store
    // 所以直接引入store对象
    const token = store.getters.token// 直接使用集成getters(方便)
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
// 响应拦截器
/*
  1.axios内部的处理机制:
    ①http状态码为2xx,3xx就会给Promise对象位置,返回成功的结果(resolve())。
    ②http状态码为4xx,5xx就会给Promise对象位置,返回错误的结果(reject())
    如果想做些操作,可以在响应拦截器中,自己来处理返回结果
    http状态码,由本次请求后,后端进行设置返回
*/
service.interceptors.response.use(
  response => { // http请求为2xx,3xx进入这里
    // 由于本次项目,成功失败都是2xx响应码,都进入成功里,需要自己手动判定
    // axios内部会把后台返回的数据直接放到data字段下,(第一个data是axios处理的)
    const { data: { success, message }} = response // 对response进行解构
    if (!success) { // 失败
      return Promise.reject(new Error(message)) // 自己设定,产生错误信息
    } else { // 成功
      // 返回response->返回的还是axios处理的结果对象(逻辑那边得.data.data)拿到后台返回值
      // 返回response.data->返回的就是后台返回的响应对象(逻辑那边拿到的真正的数据.data)拿到返回值
      return response.data // 返回到axios调用在原地留下的Promise对象位置(逻辑页面await后面)
    }
  },
  error => { // http为4xx或5xx进入这里
    // 身份过期,后台双重返回401,逻辑状态码
    // 前置非空判断(error有值,才会执行&&后面的代码)
    // 确保error有值,再 .response, .response有值,再 . status
    // 防止null.xxx 语法报错代码停止
    // if (error && error.response && error.response.status === 401) {
    //   // 身份过期, 删除所有cookie, 重置vuex, 强制回到登录页面
    // }
    // 但是账号密码失败的时候返回的是200, 用逻辑判断 - 最好统一
    // code更好, 因为401如果有多个情况, success只能判断是失败, 我们可以跟后台商量code值不同错误不同
    // 10000 成功  10002 身份过期  10004 xxxx
    if (error && error.response && error.response.data && error.response.data.code === 10002) {
      store.commit('user/RESET_STATE')
      store.commit('user/REMOVE_TOKEN') // 内部会删除本地cookie里的token
      // router.currentRoute路由对象内置的,也拿到当前页面路由的信息对象
      router.replace(`/login?redirect=${router.currentRoute.fullPath}`)
    }
    return Promise.reject(error) // 相当于reject(error)
  }
)

export default service

